package de.bk.timecalc.core;

import org.junit.Before;
import org.junit.Test;

/**
 * I know no good way to ensure that the items returned by
 * {@link ProbabilisticDistribution#select()} adhere to the given probabilistic
 * distribution. This is the best idea I have right now, although it is not
 * entirely satisfying.
 * 
 * However, this is not a unit test. It is not even an automated test. It just
 * selects many items an prints out the observed distribution. It is written as
 * a JUnit test case so it can run with the other unit tests but the results
 * need to be controlled manually.
 * 
 * @author Bastian Krol
 */
public class ProbabilisticDistributionMeasurement
{
  private static final int NUMBER_OF_ITEMS_TO_BE_SELECTED = 100000;

  private static final int[] NON_NORMALIZED_PROBABILITIES = new int[] { 2, 3,
      4, 5, 7 };
  private ProbabilisticDistribution<Integer> distribution;
  private Integer[] items;

  @Before
  public void setUp()
  {
    this.distribution = new ProbabilisticDistribution<Integer>();
    this.items = new Integer[NON_NORMALIZED_PROBABILITIES.length];
    for (int i = 0; i < NON_NORMALIZED_PROBABILITIES.length; i++)
    {
      this.items[i] = new Integer(i);
      this.distribution.add(this.items[i], NON_NORMALIZED_PROBABILITIES[i]);
    }
  }

  @Test
  public void measure()
  {
    int[] counter = new int[this.items.length];

    for (int i = 0; i < NUMBER_OF_ITEMS_TO_BE_SELECTED; i++)
    {
      Object item = this.distribution.select();
      boolean found = false;
      for (int j = 0; j < this.items.length; j++)
      {
        if (item == this.items[j])
        {
          counter[j]++;
          found = true;
          break;
        }
      }
      if (!found)
      {
        throw new RuntimeException("Item not found: " + item);
      }
    }

    System.out.println("ProbabilisticDistributionMeasurement:");
    for (int i = 0; i < this.items.length; i++)
    {
      Integer item = this.items[i];
      int expected = this.distribution.getProbability(item).times(
          NUMBER_OF_ITEMS_TO_BE_SELECTED).intValue();
      System.out.println("item " + item + ", expected " + expected
          + " times, actual " + counter[i] + " times");
    }
  }
}